/*
 * ECARX Technology Limited is the owner of the copyright and the trade secret of this software.
 * Without permission, no one has the right to obtain, disclose or use this software in any way.
 */

package com.ecarx.systemui.plugin.controller;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.location.GnssStatus;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;

import androidx.annotation.NonNull;

import com.ecarx.systemui.plugin.PluginContext;
import com.ecarx.systemui.plugin.R;
import com.ecarx.systemui.plugin.controller.base.BaseController;
import com.ecarx.systemui.plugin.utils.LogUtils;

import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;

public class GPSSController extends BaseController {

    private static final String TAG = "GPSSControllerTag";
    private LocationManager mLocationManager;

    //小于四颗卫星则无法定位
    private static final int MIN_SATELLITES_TO_LOCATE = 4;
    //根据高德磐蒲提供的数据,信噪比0~20为弱,20~30为一般,30~60为高
    private static final float GPS_SIGNAL_WEAKNESS = 20.0f;

    public static final int GPS_STATUS_NO = 0;
    public static final int GPS_STATUS_WEAK = 1;
    public static final int GPS_STATUS_HIGH = 2;

    private int currentGpsStatus = GPS_STATUS_HIGH;

    private static GPSSController mGPSSController;
    private IOnNotifyGpsIconChange mListener;
    private final List<OnGpsStatusListener> mGpsStatusListeners;


    public int getCurrentGpsStatus() {
        return currentGpsStatus;
    }


    @Override
    protected void initController(Context context) {
        initGpsStatus();
    }

    @Override
    protected void destroyController(Context context) {
        LogUtils.d(TAG, "destroy");
        if (mLocationManager != null) {
            mLocationManager.unregisterGnssStatusCallback(callback);
        }
    }

    private GPSSController(Context context) {
        super(context);
        mGpsStatusListeners = new ArrayList<>();
    }

    public static synchronized GPSSController getInstance(Context context) {
        if (mGPSSController == null) {
            mGPSSController = new GPSSController(context);
        }
        return mGPSSController;
    }

    @SuppressLint("MissingPermission")
    private void initGpsStatus() {
        mLocationManager = (LocationManager)PluginContext.getInstance().getPluginContext()
                .getSystemService(Context.LOCATION_SERVICE);
        if (mLocationManager == null) {
            LogUtils.e(TAG, "initLocation get LocationManager is null");
            return;
        }
        //TODO fwk报错，依赖tcam，FWK 暂无联调时间计划
        try {
            mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
            mLocationManager.registerGnssStatusCallback(callback);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
    }

    LocationListener locationListener = new LocationListener() {

        @Override
        public void onLocationChanged(@NonNull Location location) {
            LogUtils.i(TAG,"locationListener onLocationChanged");
        }

        @Override
        public void onLocationChanged(@NonNull List<Location> locations) {
            LocationListener.super.onLocationChanged(locations);
            LogUtils.i(TAG,"locationListener onLocationChanged list");
        }

        @Override
        public void onFlushComplete(int requestCode) {
            LocationListener.super.onFlushComplete(requestCode);
            LogUtils.i(TAG,"locationListener onFlushComplete");
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            LocationListener.super.onStatusChanged(provider, status, extras);
            LogUtils.i(TAG,"locationListener onStatusChanged");
        }

        @Override
        public void onProviderEnabled(@NonNull String provider) {
            LocationListener.super.onProviderEnabled(provider);
            LogUtils.i(TAG,"locationListener onProviderEnabled");
        }

        @Override
        public void onProviderDisabled(@NonNull String provider) {
            LocationListener.super.onProviderDisabled(provider);
            LogUtils.i(TAG,"locationListener onProviderDisabled");
        }
    };

    final GnssStatus.Callback callback = new GnssStatus.Callback() {
        @Override
        public void onSatelliteStatusChanged(GnssStatus status) {
            super.onSatelliteStatusChanged(status);
            int satelliteCount = status.getSatelliteCount();
            LogUtils.d(TAG, "onSatelliteStatusChanged satelliteCount:" + satelliteCount);
            if (satelliteCount < MIN_SATELLITES_TO_LOCATE) {
                //小于四颗卫星则无法定位,认为没有gps信号
                notifyGpsIconChange(GPS_STATUS_NO);
            } else {
                int highSignalCount = 0;
                for (int i = 0; i < satelliteCount; i++) {
                    float cn0DbHz = status.getCn0DbHz(i);
                    if (cn0DbHz >= GPS_SIGNAL_WEAKNESS) {
                        highSignalCount++;
                    }
                }
                LogUtils.d(TAG, "onSatelliteStatusChanged " + "highSignalCount:" + highSignalCount);
                if (highSignalCount < MIN_SATELLITES_TO_LOCATE) {
                    notifyGpsIconChange(GPS_STATUS_WEAK);
                } else {
                    notifyGpsIconChange(GPS_STATUS_HIGH);
                }
            }
        }
    };


    private void notifyGpsIconChange(int flag) {
        currentGpsStatus = flag;
        onGpsStatusChange(flag);
        if (GPS_STATUS_NO == flag) {
            LogUtils.d(TAG, "notifyGpsIconChange 无gps信号");
            if (mListener != null) {
                mListener.onNotifyGpsIconChange(R.drawable.ic_status_icon_gps_nosignal);
            }
        } else if (GPS_STATUS_WEAK == flag) {
            LogUtils.d(TAG, "notifyGpsIconChange gps信号弱");
            if (mListener != null) {
                mListener.onNotifyGpsIconChange(R.drawable.ic_status_icon_gps_signal_weak);
            }

        } else if (GPS_STATUS_HIGH == flag) {
            if (mListener != null) {
                mListener.onNotifyGpsIconChange(-1);
            }
        }
    }


    public interface IOnNotifyGpsIconChange {
        void onNotifyGpsIconChange(int resId);
    }

    public void setIOnNotifyGpsIconChangeListener(IOnNotifyGpsIconChange listener){
        mListener = listener;
    }


    public interface OnGpsStatusListener {
        void onStatusChange(int status);
    }

    public void addGpsStatusListener(OnGpsStatusListener onGpsStatusListener){
        if (!mGpsStatusListeners.contains(onGpsStatusListener)) {
            mGpsStatusListeners.add(onGpsStatusListener);
        }
    }

    public void removeGpsStatusListener(OnGpsStatusListener onGpsStatusListener){
        mGpsStatusListeners.remove(onGpsStatusListener);
    }

    private void onGpsStatusChange(int status){
        for (OnGpsStatusListener gpsStatusListener : mGpsStatusListeners) {
            gpsStatusListener.onStatusChange(status);
        }
    }

}
